package com.gitee.srurl.core.api.impl.id;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.gitee.srurl.core.annotation.ApiImpl;
import com.gitee.srurl.core.api.IConfigCache;
import com.gitee.srurl.core.api.IUniqueIdGenerate;
import com.gitee.srurl.core.constant.ApiTypeConstant;
import com.gitee.srurl.core.properties.SnowflakeProperties;
import com.gitee.srurl.core.util.JacksonUtil;
import com.gitee.srurl.snow.domain.SnowflakeData;
import com.gitee.srurl.snow.domain.SnowflakeReportData;
import com.gitee.srurl.snow.gen.AbstractSnowflake;
import com.gitee.srurl.snow.gen.DefaultSnowflake;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Optional;

/**
 * 雪花算法ID
 *
 * @author zxw
 * @date 2023/4/19 22:40
 */
@Slf4j
@ApiImpl(ApiTypeConstant.UniqueIdGenerate.SNOWFLAKE)
public class SnowflakeIdGenerate implements IUniqueIdGenerate {

    private final AbstractSnowflake snowflake;

    public SnowflakeIdGenerate(List<IConfigCache> configCacheList, SnowflakeProperties snowflakeProperties) {

        if (snowflakeProperties == null) {
            log.error("初始化sid参数不能为空！");
            throw new IllegalArgumentException("初始化id生成器ID参数不能为空！");
        }

        SnowflakeReportData snowflakeReportData = null;
        // 读取之前的配置
        if (CollectionUtil.isNotEmpty(configCacheList)) {
            // 去读配置文件参数
            for (IConfigCache configCache : configCacheList) {
                byte[] read = configCache.read(StrUtil.format("snowflake/snowflake_{}_{}.json",
                        snowflakeProperties.getWorkerId(), snowflakeProperties.getDataCenterId()));
                if (ArrayUtil.isNotEmpty(read)) {
                    SnowflakeReportData snowflakeReportDataTemp = JacksonUtil.parseObject(read, new TypeReference<>() {
                    });
                    // 获取最高版本号的那个
                    if (snowflakeReportData == null || snowflakeReportData.getVersion() == null) {
                        snowflakeReportData = snowflakeReportDataTemp;
                    } else {
                        Long version = snowflakeReportData.getVersion();
                        Long tempVersion = Optional.ofNullable(snowflakeReportDataTemp.getVersion()).orElse(-1L);
                        if (version < tempVersion) {
                            snowflakeReportData = snowflakeReportDataTemp;
                        }
                    }
                }
            }
        }

        long epoch = snowflakeReportData == null ? snowflakeProperties.getEpoch() : snowflakeReportData.getTwepoch();
        long lastTimestamp = snowflakeReportData == null ? -1 : snowflakeReportData.getLastTimestamp();

        SnowflakeData snowflakeData = SnowflakeData.builder()
                .epoch(epoch)
                .workerId(snowflakeProperties.getWorkerId())
                .dataCenterId(snowflakeProperties.getDataCenterId())
                .timeOffset(snowflakeProperties.getTimeOffset())
                .randomSequenceLimit(snowflakeProperties.getRandomSequenceLimit())
                .backwardsHandle(snowflakeProperties.getBackwardsHandle())
                .lastTimestamp(lastTimestamp)
                .build();
        snowflake = new DefaultSnowflake(snowflakeData);
    }

    public SnowflakeIdGenerate(SnowflakeProperties snowflakeProperties) {
        this(null, snowflakeProperties);
    }

    @Override
    public long getId() {

        return snowflake.nextId();
    }
}
